package file

import (
	"mime"
	"net/http"
	"net/url"
	"path"
	"strings"

	HTTP "../../http"
	Key "../../key"
	"../protocol"
)

// init 初始化
func init() {
	mime.AddExtensionType(".js", "application/x-javascript")
}

// File 文章路由
// ! 注: 路径需要 / 作为结束
type File struct {
	*HTTP.HTTP
	// 参数
	Path string // * 本地文件路径
	// 远程参数
	RegExp                bool   // * 启用正则
	UsingTypes            bool   // * 启用文件类型
	RemotePath            string // * 远程访问路径
	RemoteWritePath       string // * 写远程访问路径
	TogetherRootDirectory bool   // * 文件都在根目录,没有子目录
	// Key设置
	ReadKey       *Key.Key // * 读文件 Key
	UsingReadKey  bool     // * 启用读 Key
	WriteKey      *Key.Key // * 写文件 Key
	UsingWriteKey bool     // * 启用写 Key
	// 内部变量
	fileCache *Cache
}

// New 创建
// ? Path string	本地文件储存目录
// ? Time int64		缓存超时时间 秒
func (File *File) New(Path string, Time int64) *File {
	// * 处理路径
	File.Path = inPathAfter(Path, true)
	// File.RemotePath = inPathAfter(File.RemotePath, true)
	// File.RemoteWritePath = inPathAfter(File.RemoteWritePath, true)
	// * 设置变量
	File.fileCache, _ = NewCache(File.Path, Time)
	// * 读路由
	if File.RemotePath != "" {
		Protocol := &protocol.Protocol{
			Path:         File.RemotePath,
			RegExp:       File.RegExp,
			Key:          File.ReadKey,
			UsingKey:     File.UsingReadKey,
			ProtocolType: "GET",
			// * 处理过程
			Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
				// * 打开文件
				file, _ := url.PathUnescape(r.URL.String())
				// * 去除参数
				N := strings.Index(file, "?")
				if N != -1 {
					file = (file)[:N]
				}
				// * 删除路由前戳
				N = strings.LastIndex(File.RemotePath, "/")
				if N != -1 {
					file = file[N+1:]
				}
				// * 得到文件名
				if File.TogetherRootDirectory {
					N = strings.LastIndex(file, "/")
					if N != -1 {
						file = file[N+1:]
					}
				}
				// * 设置返回头
				if File.UsingTypes {
					ctype := mime.TypeByExtension(path.Ext(file))
					w.Header().Set("Content-Type", ctype)
				}
				// * 读文件
				if data, err := File.fileCache.Read(file); err == nil {
					w.WriteHeader(http.StatusOK)
					w.Write(data)
				} else {
					// * 打开文件
					if item, err := File.fileCache.Open(file); err == nil {
						w.WriteHeader(http.StatusOK)
						w.Write(item.Data)
					} else {
						w.WriteHeader(http.StatusNotFound)
					}
				}
			}}
		// * 允许跨域
		Handle := Protocol.Routing()
		Handle.CrossDomain = true
		File.Handle[Handle] = Protocol
	}
	// * 写路由
	if File.RemoteWritePath != "" {
		Protocol := &protocol.Protocol{
			Path:         File.RemoteWritePath,
			RegExp:       File.RegExp,
			Key:          File.WriteKey,
			UsingKey:     File.UsingWriteKey,
			ProtocolType: "POST",
			// * 处理过程
			Processor: func(w http.ResponseWriter, r *http.Request, v map[string]interface{}) {
				// * 得到文件路径
				file, _ := url.PathUnescape(r.URL.String())
				// * 删除路由前戳
				N := strings.LastIndex(File.RemoteWritePath, "/")
				if N != -1 {
					file = file[N+1:]
				}
				// * 得到文件名
				if File.TogetherRootDirectory {
					N := strings.LastIndex(file, "/")
					if N != -1 {
						file = file[N+1:]
					}
				}
				// * 写文件
				if value, ok := v["Data"]; ok {
					var data string
					if data, ok = value.(string); !ok {
						w.Write([]byte("参数错误"))
						return
					}
					// * 写数据
					if File.fileCache.Write(file, []byte(data)) == nil {
						w.WriteHeader(http.StatusOK)
					} else {
						w.Write([]byte("无缓冲命中"))
						return
					}
				}
			}}
		// * 允许跨域
		Handle := Protocol.Routing()
		Handle.CrossDomain = true
		File.Handle[Handle] = Protocol
	}
	return File
}

// inPathAfter 处理后戳
// ? 用于处理输入的路径后戳
func inPathAfter(s string, b bool) string {
	var n = len(s) - 1
	if n == -1 {
		return s
	}
	if s[n:] == "/" {
		if b {
			return s
		}
		return s[n:]
	}
	if b {
		return s + "/"
	}
	return s
}
